package org.atf.services;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.atf.command.AtfLocal;
import org.atf.command.AtfRemote;
import org.atf.model.dao.AtfSchedulerDAO;
import org.atf.model.dao.PreferenceDAO;
import org.atf.model.entity.JobSummary;
import org.atf.model.entity.Jobs;
import org.atf.model.entity.Preference;
import org.atf.utils.ATFUtils;
import org.atf.utils.SchedulerJobsXmlDAO;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

import com.jcraft.jsch.JSchException;

public class SchedulerJob implements Job{
	private static Logger logger = Logger.getLogger(SchedulerJob.class);
	private AtfRemote atfRemote;
	private AtfLocal atfLocal;
	AtfSchedulerDAO atfSchedulerDAO = new AtfSchedulerDAO();
	PreferenceDAO preferenceDAO= new PreferenceDAO();
	private StringBuffer output = new StringBuffer();
	private StringBuffer error = new StringBuffer();
	
	public void execute(JobExecutionContext context) throws JobExecutionException {
		// TODO Auto-generated method stub
		JobSummary jobSummary = new JobSummary();
		
		JobKey key = context.getJobDetail().getKey();
	    JobDataMap dataMap = context.getJobDetail().getJobDataMap();
	    Integer scheduleId = dataMap.getInt("jobId");
	    logger.debug("Job Execute started for Job id:"+scheduleId );
	    atfSchedulerDAO.updateScheduleCStatus(scheduleId, "RUNNING");
	    Jobs job=atfSchedulerDAO.getJobsId(scheduleId);
	    logger.debug("Job Name:"+job.getName() );
	    logger.debug("Job:"+job);
	   
	    System.out.println("Execute the jobs:"+job.getName());
	    boolean sshEnabled  = false ;
	   // List<Preference> prefList= new ArrayList<Preference> ();
	   // prefList.addAll(job.getPreference());
	    
	    Preference sshEnabledPref=preferenceDAO.getPreferenceByJobScope(job.getJobId(), "SSH_ENABLED", "JOB");
	    if(sshEnabledPref != null){
	    	sshEnabled=Boolean.valueOf(sshEnabledPref.getpValue());
	    	logger.debug("SSH ENABLED : "+sshEnabled);
	    }
	    if(sshEnabled){
	    	logger.debug("Remote Execution is enabled.. ");
	    	atfRemote= new AtfRemote();
	    	atfRemote.setOutputBuffer(output);
			atfRemote.setErrorBuffer(error);
			
	    	String username=job.getUsername();
	    	if (username == null ||username.equalsIgnoreCase("")){
	    		Preference sshUsername=preferenceDAO.getPreferenceByJobScope(job.getJobId(), "SSH_USERNAME", "JOB");
	    		if(sshUsername != null){
	    			username=sshUsername.getpValue();
	    			logger.debug("SSH Username : "+username);
	    		}
	    	}
	    	
	    	String password = job.getPassword();
	    	if(password == null || password.equalsIgnoreCase("")){
	    		Preference sshUsername=preferenceDAO.getPreferenceByJobScope(job.getJobId(), "SSH_PASSWORD", "JOB");
	    		if(sshUsername != null){
	    			username=sshUsername.getpValue();
	    			logger.debug("SSH Username : "+username);
	    		}
	    	}
	    	String sshKnownFile="";
	    	Preference sshKnownHostFile=preferenceDAO.getPreferenceByJobScope(job.getJobId(), "SSH_KNOWN_HOST_FILE", "JOB");
	    	if(sshKnownHostFile != null){
	    		sshKnownFile=sshKnownHostFile.getpValue();
	    		logger.debug("SSH Known File : "+sshKnownFile);
	    	}
	    	
	    	atfRemote.setUsername(username);
	    	atfRemote.setPassword(password);
	    	atfRemote.setKnownHostsFilename(sshKnownFile);
	    	atfRemote.setHostname(job.getServerName());
	    	atfRemote.setPort(job.getPort());
	    	
	    	String cmd="";
	    	if(job.getScriptUser() != null && !job.getScriptUser().equalsIgnoreCase("") ){
	    		cmd=job.getScriptUser()+" ";
	    	}
	    	cmd+=job.getScript();
			logger.debug("Command to execute: "+cmd);
			atfRemote.setCommand(cmd);
			try {
				if(!cmd.equalsIgnoreCase("")){
					jobSummary.setStartDate(Calendar.getInstance().getTime());
					
					atfRemote.remoteExecute();
					while(true){
						if(!atfRemote.isRunning()){
							break;
						}
						try{Thread.sleep(1000);}catch(Exception e){};
					}
					jobSummary.setEndDate(Calendar.getInstance().getTime());
				}else{
					error.append("Command is not found");
				}
				
			} catch (JSchException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				error.append(e.getMessage());
				jobSummary.setEndDate(Calendar.getInstance().getTime());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				error.append(e.getMessage());
				jobSummary.setEndDate(Calendar.getInstance().getTime());
			}	
	    }else{
	    	logger.debug("Local Execution is enabled.. ");
	    	atfLocal= new AtfLocal();
	    	atfLocal.setOutputBuffer(output);
	    	atfLocal.setErrorBuffer(error);
	    	String cmd="";
	    	if(job.getScriptUser() != null && !job.getScriptUser().equalsIgnoreCase("") ){
	    		cmd=job.getScriptUser()+" ";
	    	}
	    	cmd+=job.getScript();
	    	atfLocal.setCommand(cmd);
	    	try {
	    		jobSummary.setStartDate(Calendar.getInstance().getTime());
				atfLocal.localExecute();
				while(true){
					if(!atfLocal.isRunning()){
						break;
					}
					try{Thread.sleep(1000);}catch(Exception e){};
				}
				jobSummary.setEndDate(Calendar.getInstance().getTime());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				error.append(e.getMessage());
				jobSummary.setEndDate(Calendar.getInstance().getTime());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				error.append(e.getMessage());
				jobSummary.setEndDate(Calendar.getInstance().getTime());
			}
	    }
	    logger.trace(output.toString());
	    logger.trace(error.toString());
	    jobSummary.setJobOutput(output.toString());
	    jobSummary.setJobError(error.toString());
	   // job.addJobSummary(jobSummary);
	    
	    Calendar sCal=Calendar.getInstance();
	 //   job.setLastRun(sCal.getTime());
	   // job.setNextRun(context.getNextFireTime());
	    logger.debug("Updating the Job Run Time");
	    jobSummary.setJobId(job.getJobId());
	    jobSummary.setJobName(job.getName());
	    jobSummary.setRegion(job.getRegion());
	    atfSchedulerDAO.addSchedulerJobSummary(jobSummary);
	    atfSchedulerDAO.updateJobLastRun(job.getJobId(), sCal.getTime());
	    atfSchedulerDAO.updateJobNextRun(job.getJobId(), context.getNextFireTime());
	   if(job.getSendEmail().equalsIgnoreCase("true") ){
		   logger.info("Sending Email...");
		   if(job.getEmailTo() != null && !job.getEmailTo().equalsIgnoreCase("")){
			   logger.info("Sending To Email..."+job.getEmailTo());
			   String message= output.toString();
			   message+="ERROR: ***********************\n";
			   message+=error.toString();
			   
			   String subject="Scheduler Job Name: "+job.getName();
			   String fromEmail="";
			   Preference fromEmailTo=preferenceDAO.getPreferenceByJobScope(job.getJobId(), "SMTP_FROM_ADDRESS", "JOB");
		    	if(fromEmailTo != null){
		    		fromEmail=fromEmailTo.getpValue();
		    		
		    	}
		    	logger.debug("From Email :"+fromEmail+" Subject: "+subject);
		    	logger.trace(message);
		    	ATFUtils.sendTextEmail(job.getEmailTo(),fromEmail,subject,message);
		   }
   
	   }
	   atfSchedulerDAO.updateScheduleCStatus(scheduleId, "STOPPED");
	    
	}
	
	

}
